#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <error.h>
#include "utils.h"
#include "err.h"

void  print_error(err_strc current_error)
{
    switch (current_error.errnum)
    {
    case SHELL_PARSE_ERROR: fprintf(stderr, "\nShell: Parsing error ");
        break;
    case SHELL_CANT_OPENFILE: fprintf(stderr, "\nShell: Cant open file ");
        break;
    case SHELL_INVALID_FILENAME: fprintf(stderr, "\nShell: Invalid filename ");

    case SHELL_KILL_ERR: fprintf(stderr, "\nKilled: ");
        break;
    case SHELL_STUB_ERR: fprintf(stderr, "\nShell:Stub: ");
        break;
    default: fprintf(stderr, "\nShell: ");
    }


    if (current_error.attrib & SHELL_SYSTEM)
    {
        if (current_error.errmsg == NULL   || strlen(current_error.errmsg)  < (256 * sizeof(char)))
            current_error.errmsg =
                    (char *)xrealloc(current_error.errmsg, sizeof(char) * 256);
        strerror_r(current_error.errnum, current_error.errmsg, 256 * sizeof(char));
    }
    fprintf(stderr, "%s\n", current_error.errmsg);

    free(current_error.errmsg);
    if (current_error.attrib & SHELL_CRITICAL)
        abort();
    if (current_error.attrib & SHELL_FORKED_ERROR)
        exit(0);
}

int get_args_cnt(const char *fmt, size_t len)
{
    int res = 0;
    for (size_t i = 0; i < len; i++)
        if (len && (i < (len - 1)) && (fmt[i] == '%' && fmt[i + 1] != '%'))
            res++;
    return res;
}

err_strc make_error_struct(int errnum, int8_t attrib, const char *fmt, ...)
{
    err_strc res;
    res.errnum = errnum;
    res.attrib = attrib;
    va_list args, count_args;
    va_start(args, fmt);
    va_copy(count_args, args);

    size_t len = strlen(fmt);
    int n = get_args_cnt(fmt, len);
    for (int i = 0; i < n; i++)
    {
        char *str = va_arg(count_args, char *);
        len += strlen(str);
    }
    res.errmsg = (char *)xmalloc(len);
    vsprintf(res.errmsg, fmt, args);
    va_end(args);
    return res;
}

err_strc init_no_err()
{
    err_strc res;
    res.errnum = res.attrib = 0;
    res.errmsg = NULL;
    return res;
}

err_strc  make_quit_error()
{
    err_strc res;
    res.attrib = 0;
    res.errnum = SHELL_QUIT_ERROR;
    res.errmsg = "Good bye";
    return res;
}

